package com.dycn.posdashboard.util;

import java.text.ParseException;
import java.util.Date;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.CronTrigger;
import org.quartz.InterruptableJob;
import org.quartz.Job;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.SchedulerListener;
import org.quartz.Trigger;
import org.quartz.TriggerListener;
import org.quartz.impl.StdSchedulerFactory;


public class QuartzManager {
	private static final Log log = LogFactory.getLog("com.yihaodian.bi.metaapp.util.QuartzManager");
    //protected final Log log = LogFactory.getLog(getClass());
    private static SchedulerFactory sf= new StdSchedulerFactory();
    
    private static String           LUCENE_INDEX_JOB_GROUP_NAME= "lucene_index_job_group";
    private static String          LUCENE_INDEX_TRIGGER_GROUP_NAME = "lucene_index_job_trigger";
    
    private static String           METACOLUMNDEF_SYNC_JOB_GROUP_NAME= "metaColumndefination_sync_job_group";
    private static String          METACOLUMNDEF_SYNC_TRIGGER_GROUP_NAME = "metaColumndefination_sync_job_trigger";
    
    private static String           DEFAULT_JOB_GROUP_NAME= "default_job_group";
    private static String         DEFAULT_TRIGGER_GROUP_NAME = "default__job_trigger";
    
    private static QuartzManager _instance;
    
    private static Scheduler _sched;
    
    private QuartzManager(){
    	
    }
    
    
    public static QuartzManager getInstance() throws SchedulerException{
    	if(_instance==null){
    		_instance=new QuartzManager();
	    	try {
				_sched= sf.getScheduler();
			} catch (SchedulerException e) {
				
				e.printStackTrace();
				log.info(" StdSchedulerFactory.getScheduler exception :::"+e.toString());
				throw e;
			}
	    	
	
	    	_sched.addGlobalTriggerListener(new TriggerListener(){
	
				@Override
				public String getName() {
					
					return "METADAT_SYS_JOB_TIGGER_LISTENER";
				}
	
				@Override
				public void triggerComplete(Trigger arg0, JobExecutionContext arg1,
						int arg2) {
					
					log.info("Triggle["+arg0.getName()+"] triggerComplete When "+arg1.getFireTime()+" result:"+arg2+" next trigger on " +arg1.getNextFireTime());
				}
	
				@Override
				public void triggerFired(Trigger arg0, JobExecutionContext arg1) {
					log.info("Triggle["+arg0.getName()+"] "+" triggerFired When "+arg1.getFireTime());
				}
	
				@Override
				public void triggerMisfired(Trigger arg0) {
					log.info("Triggle["+arg0.getName()+"] "+" triggerMisfired "+arg0.getMisfireInstruction());
				}
	
				@Override
				public boolean vetoJobExecution(Trigger arg0,
						JobExecutionContext arg1) {
					return false;
				}
	    		
	    	});
	    	_sched.start();
	    	
	    	_sched.addSchedulerListener(new SchedulerListener(){

				@Override
				public void jobAdded(JobDetail arg0) {
					
					try {
						log.info("["+_sched.getSchedulerName()+"]jobAdded..... "+arg0.getName()+" "+arg0.getGroup());
					} catch (SchedulerException e) {
						
						e.printStackTrace();
					}
				}

				@Override
				public void jobDeleted(String jobName, String arg1) {
					
					try {
						log.info("["+_sched.getSchedulerName()+"]jobDeleted..... "+jobName+" "+arg1);
						String dbExecuteMonitorKey="Monitor_JOB_KEY_"+jobName;
						log.info("["+_sched.getSchedulerName()+"]jobDeleted..... dbExecuteMonitorKey:"+dbExecuteMonitorKey);
						//DBStatementMonitor2.getInstance().stopSqlQuery(dbExecuteMonitorKey,true);
						//执行job被删除后的后续处理工作
						
					} catch (SchedulerException e) {
						
						e.printStackTrace();
					}
				}

				@Override
				public void jobScheduled(Trigger arg0) {
					
					try {
						log.info("["+_sched.getSchedulerName()+"]jobScheduled..... "+arg0.getName()+" "+arg0.getGroup());
					} catch (SchedulerException e) {
						
						e.printStackTrace();
					}
				}

				@Override
				public void jobUnscheduled(String arg0, String arg1) {
					
					try {
						log.info("["+_sched.getSchedulerName()+"]jobUnscheduled..... "+arg0+" "+arg1);
					} catch (SchedulerException e) {
						
						e.printStackTrace();
					}
				}

				@Override
				public void jobsPaused(String arg0, String arg1) {
					try {
						log.info("["+_sched.getSchedulerName()+"]jobsPaused..... "+arg0+" "+arg1);
					} catch (SchedulerException e) {
						
						e.printStackTrace();
					}
				}

				@Override
				public void jobsResumed(String arg0, String arg1) {
					try {
						log.info("["+_sched.getSchedulerName()+"]jobsResumed..... "+arg0+" "+arg1);
					} catch (SchedulerException e) {
						
						e.printStackTrace();
					}
				}

				@Override
				public void schedulerError(String arg0, SchedulerException arg1) {
					
					try {
						log.info("["+_sched.getSchedulerName()+"]schedulerError..... "+arg0+" "+arg1.toString());
					} catch (SchedulerException e) {
						
						e.printStackTrace();
					}
				}

				@Override
				public void schedulerInStandbyMode() {
					
					try {
						log.info("["+_sched.getSchedulerName()+"]schedulerInStandbyMode.....");
					} catch (SchedulerException e) {
						
						e.printStackTrace();
					}
				}

				@Override
				public void schedulerShutdown() {
					
					try {
						log.info("["+_sched.getSchedulerName()+"]schedulerShutdown.....");
					} catch (SchedulerException e) {
						
						e.printStackTrace();
					}
				}

				@Override
				public void schedulerShuttingdown() {
					
					try {
						log.info("["+_sched.getSchedulerName()+"]schedulerShuttingdown.....");
					} catch (SchedulerException e) {
						
						e.printStackTrace();
					}
				}

				@Override
				public void schedulerStarted() {
					
					try {
						log.info("["+_sched.getSchedulerName()+"]schedulerStarted.....");
					} catch (SchedulerException e) {
						
						e.printStackTrace();
					}
				}

				@Override
				public void triggerFinalized(Trigger arg0) {
					
					log.info("Triggle["+arg0.getName()+"] "+" triggerFinalized ");
				}

				@Override
				public void triggersPaused(String arg0, String arg1) {
					
					try {
						log.info("["+_sched.getSchedulerName()+" ] triggersPaused "+arg0+" "+arg1);
					} catch (SchedulerException e) {
						
						e.printStackTrace();
					}
				}

				@Override
				public void triggersResumed(String arg0, String arg1) {
					
					try {
						log.info("["+_sched.getSchedulerName()+" ] triggersResumed "+arg0+" "+arg1);
					} catch (SchedulerException e) {
						
						e.printStackTrace();
					}
				}
	    		
	    	});
    	}
    	
    	return _instance;
    }

    private String[] getGroupAndTriggerNameByJobType(Integer jobType){
//    	if(jobType.intValue()==MetaJob.META_JOB_TYPE_METADATAS_LUCENE_INDEX){
//    		return new String[]{LUCENE_INDEX_JOB_GROUP_NAME,LUCENE_INDEX_TRIGGER_GROUP_NAME};
//    	}else if(jobType.intValue()==MetaJob.META_JOB_TYPE_METADATAS_LUCENE_INDEX){
//    		return new String[]{METACOLUMNDEF_SYNC_JOB_GROUP_NAME,METACOLUMNDEF_SYNC_TRIGGER_GROUP_NAME};
//    	}else{
//    		return new String[]{DEFAULT_JOB_GROUP_NAME,DEFAULT_TRIGGER_GROUP_NAME};
//    	}
    	
    	return new String[]{DEFAULT_JOB_GROUP_NAME,DEFAULT_TRIGGER_GROUP_NAME};
    }
    
    /**
     * 添加一个定时任务，使用默认的任务组名，触发器名，触发器组名
     * @param jobName 任务名
     * @param job     任务
     * * @param userSqlInfo    用户信息
     * @throws SchedulerException
     * @throws ParseException
     */
    public void addJob(InterruptableJob job,String cronExpression,  Integer metaJobType,String uniMetaJobName,Object jobBoundData,Object metaModelDatasManageServices) throws SchedulerException,ParseException {
    	String[]  groupAndTriggerNames=getGroupAndTriggerNameByJobType(metaJobType);
    	
    	String jobGroupName=groupAndTriggerNames[0];
    	String triggerGroupName=groupAndTriggerNames[1];
    	String jobKeyName=uniMetaJobName;
    	
    	log.info("addJob for ..."+jobKeyName);

    	JobDetail jobDetail = new JobDetail("JB_"+jobKeyName, jobGroupName, job.getClass());//任务名，任务组，任务执行类
        jobDetail.getJobDataMap().put("info", jobBoundData);
        jobDetail.getJobDataMap().put("dataServices", metaModelDatasManageServices);

        
        log.info("add to job for getCronExpression:"+cronExpression);
        //触发器
        CronTrigger trigger = new CronTrigger("TR_"+jobKeyName, triggerGroupName);//触发器名,触发器组
        Date nextFireDateTime=trigger.getFireTimeAfter(new Date());
        //log.info("getCronExpression:"+userSqlInfo.getCronExpression());
        log.info("trigger.getFireTimeAfter(afterTime):"+nextFireDateTime);
        if(nextFireDateTime==null){
            log.info("job :" + "-" + uniMetaJobName + 
            		"["+cronExpression + "] 不会有下一次执行周期");
        	return;
        }
        _sched.scheduleJob(jobDetail, trigger);
        //启动
        if (!_sched.isShutdown()) {
            //sched.start();
            log.info("job :" + "-" + uniMetaJobName
                    + "["+cronExpression + "] started. next fire time:"+trigger.getNextFireTime());

        }
    }
    
    public void addJob(Job job,String cronExpression, Integer metaJobType,String uniMetaJobName,Object jobBoundData,Object metaModelDatasManageServices) throws SchedulerException,ParseException {
    	String[]  groupAndTriggerNames=getGroupAndTriggerNameByJobType(metaJobType);
    	
    	String jobGroupName=groupAndTriggerNames[0];
    	String triggerGroupName=groupAndTriggerNames[1];
    	String jobKeyName=uniMetaJobName;
    	
    	log.info("addJob for ..."+jobKeyName);

    	JobDetail jobDetail = new JobDetail("JB_"+jobKeyName, jobGroupName, job.getClass());//任务名，任务组，任务执行类
        jobDetail.getJobDataMap().put("info", jobBoundData);
        jobDetail.getJobDataMap().put("dataServices", metaModelDatasManageServices);

        
        log.info("add to job for getCronExpression:"+cronExpression);
        //触发器
        CronTrigger trigger = new CronTrigger("TR_"+jobKeyName, triggerGroupName);//触发器名,触发器组
        Date nextFireDateTime=trigger.getFireTimeAfter(new Date());
        //log.info("getCronExpression:"+userSqlInfo.getCronExpression());
        log.info("trigger.getFireTimeAfter(afterTime):"+nextFireDateTime);
        if(nextFireDateTime==null){
            log.info("job :" + "-" + uniMetaJobName + 
            		"["+cronExpression + "] 不会有下一次执行周期");
        	return;
        }
        _sched.scheduleJob(jobDetail, trigger);
        //启动
        if (!_sched.isShutdown()) {
            //sched.start();
            log.info("job :" + "-" + uniMetaJobName
                    + "["+cronExpression + "] started. next fire time:"+trigger.getNextFireTime());

        }
    }
    
    public  void addJob( JobDetail jobDetail,String time) throws SchedulerException, ParseException {
        //Scheduler sched = sf.getScheduler();
        //JobDetail jobDetail = new JobDetail(jobName, JOB_GROUP_NAME, job.getClass());//任务名，任务组，任务执行类
        //触发器
        CronTrigger trigger = new CronTrigger(jobDetail.getName(), "trigger_name");//触发器名,触发器组
        trigger.setCronExpression(time);//触发器时间设定
        _sched.scheduleJob(jobDetail, trigger);
        //启动
        //if (!_sched.isShutdown()) _sched.start();
    }
    
    /**
     * 移除一个任务
     * @param jobName
     * @param jobGroupName
     * @param triggerName
     * @param triggerGroupName
     * @throws SchedulerException
     */
     public void removeJob(String jobName,Integer jobType)throws SchedulerException {
     	String[]  groupAndTriggerNames=getGroupAndTriggerNameByJobType(jobType);
    	
     	String jobGroupName=groupAndTriggerNames[0];
     	//String triggerGroupName=groupAndTriggerNames[1];

     	log.info("removeJob:"+jobName);
     	_sched.unscheduleJob(jobName,jobGroupName);
     	_sched.deleteJob(jobName, jobGroupName);//删除任务
     	_sched.interrupt(jobName, jobGroupName);
     }

    /** */
    /**
    * 修改一个任务的触发时间
    * @param triggerName
    * @param triggerGroupName
    * @param time
    * @throws SchedulerException
    * @throws ParseException
    */
    public void modifyJobTime(String triggerName, String triggerGroupName, String time)throws SchedulerException,ParseException {
        //Scheduler sched = sf.getScheduler();
        Trigger trigger = _sched.getTrigger(triggerName, triggerGroupName);
        if (trigger != null) {
            CronTrigger ct = (CronTrigger) trigger;
            //修改时间
            ct.setCronExpression(time);
            //重启触发器
            _sched.resumeTrigger(triggerName, triggerGroupName);
        }
    }
   
    /**
     * 获取指定任务的下一次执行时间
     * 如果没有指定的job，那么返回null
     * @param jobName
     * @return
     * @throws SchedulerException
     */
    public Date getNextExecutionTime(String jobName,String jobTriggerGroupName) throws SchedulerException{
    	 //Scheduler sched = sf.getScheduler();
    	 if(_sched.getTrigger(jobName, jobTriggerGroupName)!=null){
    		return _sched.getTrigger(jobName, jobTriggerGroupName).getNextFireTime();
    	 }else{
    		 return null;
    	 }
    }
    
    /** */
    /**
    * 移除一个任务
    * @param jobName
    * @param jobGroupName
    * @param triggerName
    * @param triggerGroupName
    * @throws SchedulerException
    */
    public void removeJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName)throws SchedulerException {
    	log.info("removeJob:"+jobName);
    	_sched.unscheduleJob(jobName,jobGroupName);
    	_sched.deleteJob(jobName, jobGroupName);//删除任务
    	_sched.interrupt(jobName, jobGroupName);
    }
}
